package maze

import (
	"gddgame.cc/galaxy/binocle"
	"gddgame.cc/galaxy/binocle/module/report"
	"gddgame.cc/galaxy/common/bootstrap"
	"gddgame.cc/galaxy/core/routers"
	"gddgame.cc/galaxy/core/sdk"
	"gddgame.cc/galaxy/project/maze/maze/controller"
	"gddgame.cc/galaxy/project/maze/maze/namespace"
	"gddgame.cc/galaxy/project/maze/maze/router"
	"gddgame.cc/galaxy/satellite/formula/nebula"
	"gddgame.cc/galaxy/server/composer"
	"gddgame.cc/galaxy/server/web"
)

const (
	Version = "1.0.0"
)

type Config struct {
	Node      string         `json:"node"`
	Address   string         `json:"address"`
	Options   nebula.Options `json:"options" galaxy:"option"`
	AppKey    string         `json:"app_key"`
	AppSecret string         `json:"app_secret"`
	Gateway   string         `json:"gateway"`
}
type Component struct {
	Config *Config
	Nebula *nebula.Server

	Web web.Engine `inject:""`

	composer.Composer `inject:""`

	Boot *bootstrap.Boot `inject:""`

	Binocle binocle.Agent `inject:""`
}

func (c *Component) Init(register composer.Register, builder composer.Builder) error {
	// 注册为应用
	agent, err := c.Binocle.Application(binocle.Config{
		Name:    "maze",
		Node:    c.Config.Node,
		Version: Version,
	})
	if err != nil {
		return err
	}

	if err := builder.BindInstance("boot", c.Boot); err != nil {
		return err
	}
	if err := builder.BindInstance("agent", agent); err != nil {
		return err
	}

	client, err := sdk.NewAppClient(builder, c.Boot, c.Config.AppKey, c.Config.AppSecret)
	if err != nil {
		return err
	}

	// 初始化系统
	if err := controller.InitGame(builder, agent, client); err != nil {
		return err
	}

	s, err := nebula.NewServer(builder, "", "", &c.Config.Options)
	if err != nil {
		return err
	}
	s.SetDebug(builder.IsDebug())

	register.Attach(c.Web.Register(c.Config.Address, func(r web.Router, handler web.RouterHandler) error {
		// 挂载websocket
		if err := s.Attach(r); err != nil {
			return err
		}

		if err := routers.ProjectUserHandler("/user", builder, handler("/user"), client); err != nil {
			return err
		}
		routers.GatewayHandler("/gateway", builder, handler("/gateway"), client, c.Config.Gateway)
		router.SystemHandler("/system", builder, handler("/system"))

		return nil
	}))

	register.Attach(s.Register(func(handler nebula.NamespaceHandler) error {
		return namespace.InitHandler(builder, client, handler)
	}))

	register.AttachListener(s)

	c.Nebula = s

	// 服务依赖设置
	agent.Depend("orbit")

	// 设定监控项
	agent.AddMetrics().Type(report.BothMetric).Exec("online", func(key string) float32 {
		return float32(s.ClientNum())
	})

	return nil
}
